package edu.siu.math.egut.main;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;

import edu.siu.math.egut.io.Algorithms;
import edu.siu.math.egut.util.LaurentPolynomial;
import edu.siu.math.egut.util.LaurentPolynomialReadException;
import edu.siu.math.egut.util.ExceptionalGroupElement;

/**
 * Facilitates analysis of the action of one unipotent group on the characters of another.  
 * 
 * The user is prompted for the name of a LiE monfile containing two matrices, to be interpreted
 * as lists of roots, then for a polynomial in variables indexed by the roots from the 
 * second list.  The effect on this polynomial of conjugating a unipotent in general position
 * determined by the second list by one determined by the first, and then making changes of 
 * variable, is computed and displayed.
 * 
 * TODO 
 * add more flexibility for the method of input
 * add capacity to customize variable names
 * add capacity to store and retrieve these customizations.
 * add "this root list does indeed define a unipotent subgroup" checking
 * determine whether it would be possible to better  optimize the conjugation orders 
 *     if a vector determining a positive linear functional on the full root set 
 *     were given as well.
 * add "these two groups together again define a unipotent subgroup" checking
 * add "this group normalizes that group" checking. 
 * add "this polynomial defines a character" checking 
 * (Though it's not inconceivable that a case where it does not could be of interest.)
 * 
 * @author josephhundley
 *
 */
public class Action {

    /**
     * @param args (Ignored.)
     */
    public static void main(String[] args) {
	// Prompt the user for a file name.
	System.out.println("The purpose of this program is to compute psi(delta u delta^{-1}), \n" +
			"where u and delta are elements in general position of unipotent subgroups \n" +
			"U and Delta determined by lists of roots, such that Delta normalized U.\n" +
			"\n\n" +
			"The first step is to input the lists of roots which determine U and Delta.\n" +
			"\n\n" +
			"At this time the only method for doing so is to give the name of a file which \n" +
			"contains the two lists of roots, with Delta first, as matrices formatted in the \n" +
			"style of LiE output (i.e., bracketed, comma separated lists of bracketed, comma\n" +
			"separated lists)." +
			"\n\n" +
			"Please input a filename.");
	
	// get filename
	Scanner scanner = new Scanner(System.in);
	String filename =  edu.siu.math.egut.io.Algorithms.getFileName(scanner);
	String s;
	try {
	    s = Algorithms.fileToString(filename);
	} catch (FileNotFoundException e) {
	    System.out.print("File \""+filename+"\" not found.");
	    e.printStackTrace();
	    System.exit(1);
	    s="[[1]],[[1]]";  // to ensure that s is always initialized before its use later... though this 
	    // line would never be read...
	}
	int[][] m1=new int[1][1];
	int[][] m2 = new int[1][1];
	try {
	    m1 = Algorithms.readLiEMatrix(s);

	    m2 = Algorithms.readLiEMatrix(s, s.indexOf("]]")+2);
	} catch (Exception e) {
	    System.out.println("Problem reading file.");
	    e.printStackTrace();
	    System.exit(1);
	}
	
	
	// form the initial unipotents d and u. 
	ExceptionalGroupElement delta = new ExceptionalGroupElement( m1, "d");
	ExceptionalGroupElement u = new ExceptionalGroupElement(m2, "u");
	
	// Now get the polynomial.
	System.out.print(u);
	System.out.println("Next, please input a polynomial in the variables corresponding to the roots " +
			"from the second matrix as above.");
	LaurentPolynomial p = edu.siu.math.egut.io.Algorithms.getPoly(scanner);
	
/* It no longer seems to me that there is much to be gained by performing changes of variable in the order naturally 
 * determined by the set of roots given.  
 * 
 * However, the idea of having the user input a vector which determines a grading on the unipotent group seems
 * not without promise for other applications...	
	//Get a vector used to order the roots.  
	System.out.println("The last thing that is needed is a vector used to order the roots, so that changes of variable" +
			"can be made in an efficient fashion.  If the roots are all positive, one may use a vector of " +
			"all ones.  If they all lie in some parabolic, it may be more efficient to use a vector with ones" +
			"only at the positions corresponding to simple roots that are in the unipotent radical of the " +
			"parabolic.  If they are not all positive the LiE initfile function \"chamber\" may be used to " +
			"find a Weyl element which maps them all to positive roots.\n\n  Please input the vector as a " +
			"single integer, with the number of digits corresponding to the rank of your group.  (For example, " +
			"11 will be read as [1,1] if the group is G2.");
	
	
	int vectorAsInt =  Integer.parseInt(scanner.nextLine());// TODO see how robust that is, can I crash it with non-integral input?
	
	int[] vector = new int[m1[0].length];
	for( int i = 0; i < m1[0].length; i++){
	    vector[i] = vectorAsInt %10;
	    vectorAsInt = vectorAsInt/10;
	}
*/	
	
	//multiply u by d on the left 
	u = ExceptionalGroupElement.times(delta, u);

	// move all the sunipotents from delta to the right and out.
	// make changes of variable in u to keep it simple.
	int next = u.lastIndexOf(m1);

	while (next != -1) {
	    u.pushFarRightAndRemove(next);
	    for( int i = 0 ; i < u.getNumberOfTerms(); i++){
		String s1 = u.stringOf(u.get(i));
		if( s1 != null ){
		    LaurentPolynomial p1 = LaurentPolynomial.create(s1).times(2).minus(u.get(i).getPolynomial());
		    p = p.replace(s1, p1);
		    u.replace( s1, p1);
			
			
		    
		}// end if s1 not null
		
	    }// end for each term...
	    
	    next = u.lastIndexOf(m1);
	} // end while next != -1


	System.out.println(u);
	System.out.println(p);
	
	
	
	System.out.println("End program Action.");

    }// end main type

}// end class declaration
